import java.io.*;
import java.util.List;
import com.db4o.*;
import com.db4o.query.Predicate;

public class PopulateDatabase {
	/* Variable for reading from console and files */
	BufferedReader br, br1, br2, br3;
	private int total;
	/* Variable for opening a database */
	ObjectContainer db;
	/* Variable for storing track objects */
	Track track1, track2;
	/* Variable for storing station objects */
	Station st;

	/**
	 * @param args
	 */
	public PopulateDatabase() throws Exception {
		/* For reading for the console */
		// br = new BufferedReader(new InputStreamReader(System.in));
		br = new BufferedReader(new FileReader("PopulateDatabaseFile"));
		/* For reading for the text file for station */
		br1 = new BufferedReader(new FileReader("station.txt"));
		/* For reading for the track text file */
		br2 = new BufferedReader(new FileReader("track.txt"));
	}

	public void openDatabase() {
		db = Db4oEmbedded.openFile(Db4oEmbedded.newConfiguration(),
				"Routing Management System");
	}

	public void closeDatabase() {
		db.close();
	}

	public void populateStations() throws IOException {
		/* Reading the first line of the file */
		String str = br1.readLine();
		int counter = 6;
		/* 1st validation: Validating if the first line is a null */
		if (str == null) {
			// System.out.println("No content in file");
			return;
		}
		/* Storing the total number of stations inside the variable "total" */
		total = Integer.parseInt(str);
		Station station = null;
		while ((str = br1.readLine()) != null) {
			if (counter == 6) {
				/* Every time a new station will be generated */
				station = new Station();
				station.setStationCode(Integer.parseInt(str));
				counter--;
			} else if (counter == 5) {
				station.setStationName(str);
				counter--;
			} else if (counter == 4) {
				station.setLocation(str);
				counter--;
			} else if (counter == 3) {
				station.setState(str);
				counter--;
			} else if (counter == 2) {
				station.setLatitude(Double.parseDouble(str));
				/* The Latitude will be stored */
				db.store(station);
				counter--;
			} else if (counter == 1) {
				/* Storing the latitude */
				station.setLongitude(Double.parseDouble(str));
				/* The station will be finally stored */
				db.store(station);
				/*
				 * Changing the counter value because again it has to start
				 * reading
				 */
				counter = 6;
			}
		}
	}

	/* It will retrieve the object from the database as per the station code */
	Station retrieveStationObject(final int stationCode) {
		/* Code to retrieve a particular object */
		@SuppressWarnings("serial")
		List<Station> station = db.query(new Predicate<Station>() {
			public boolean match(Station station) {
				return station.getStationCode() == stationCode;
			}
		});
		Station st = station.get(0);
		return st;
	}

	Track retrieveTrackObject(final int station1, final int station2) {
		@SuppressWarnings("serial")
		List<Track> track1 = db.query(new Predicate<Track>() {
			public boolean match(Track track) {
				return track.getNextStation() == station1
						&& track.getPrevStation() == station2;
			}
		});
		if (track1.size() != 0) {
			Track tr = track1.get(0);
			return tr;
		} else
			return null;
	}

	public void updateStationObject(Track track1, Track track2) {
		st = retrieveStationObject(track1.getNextStation());
		/* Validation for station */
		if (st == null)
			return;
		// JOptionPane.showMessageDialog(null, st.getStationCode());
		st.getAdjacentStations().add(track1.getPrevStation());
		st.getListOfTracks().add(track1.getTrackCode());
		st.getListOfTracks().add(track2.getTrackCode());
		/*
		 * We need to serialize the objects inside objects because only
		 * variables re directly serialized
		 */
		db.store(st.getAdjacentStations());
		db.store(st.getListOfTracks());
		/* Finally we serialize the outside object */
		db.store(st);

		/* Code to retrieve the object for that particular Station */
		st = retrieveStationObject(track1.getPrevStation());
		/* Validation for station */
		if (st == null)
			return;
		// JOptionPane.showMessageDialog(null, st.getStationCode());
		st.getAdjacentStations().add(track1.getNextStation());
		st.getListOfTracks().add(track1.getTrackCode());
		st.getListOfTracks().add(track2.getTrackCode());
		/*
		 * We need to serialize the objects inside objects because only
		 * variables re directly serialized
		 */
		db.store(st.getAdjacentStations());
		db.store(st.getListOfTracks());
		/* Finally we serialize the outside object */
		db.store(st);
	}

	public void populateTracks() throws IOException {
		/* Reading the first line of the file */
		String str = br2.readLine();
		int counter = 4;
		/* 1st validation: Validating if the first line is a null */
		if (str == null) {
			System.out.println("No content in file");
			return;
		}
		/* Storing the total number of stations inside the variable "total" */
		total = Integer.parseInt(str);

		while ((str = br2.readLine()) != null) {
			if (counter == 4) {
				/* Every time a new station will be generated */
				track1 = new Track();
				track2 = new Track();
				track1.setTrackCode(Integer.parseInt(str));
				track2.setTrackCode(Integer.parseInt(str) + 1);
				counter--;
			} else if (counter == 3) {
				track1.setNextStation(Integer.parseInt(str));
				track2.setPrevStation(Integer.parseInt(str));
				counter--;
			} else if (counter == 2) {
				track1.setPrevStation(Integer.parseInt(str));
				track2.setNextStation(Integer.parseInt(str));
				counter--;
			} else if (counter == 1) {
				track1.setLengthOfTrack(Integer.parseInt(str));
				track2.setLengthOfTrack(Integer.parseInt(str));
				/* The station will be finally stored */
				db.store(track1);
				db.store(track2);
				updateStationObject(track1, track2);
				counter = 4;
			}
		}
	}

	/* Function to clear the database */
	public void clearDatabase() {
		@SuppressWarnings("rawtypes")
		ObjectSet result = db.queryByExample(Station.class);
		while (result.hasNext()) {
			db.delete(result.next());
		}

		@SuppressWarnings("rawtypes")
		ObjectSet result1 = db.queryByExample(Track.class);
		while (result1.hasNext()) {
			db.delete(result1.next());
		}
		@SuppressWarnings("rawtypes")
		ObjectSet result2 = db.queryByExample(Train.class);
		while (result2.hasNext()) {
			db.delete(result2.next());
		}
	}

	public static void main(String[] args) {
		int choice = 1;
		PopulateDatabase p = null;
		try {
			p = new PopulateDatabase();
		} catch (Exception e) {
			e.printStackTrace();
		}
		p.openDatabase();

		while (choice == 1) {
			// System.out
			// .print("Enter 1 to Populate the stations\nEnter 2 to Populate the tracks\nEnter 3 to Populate the trains\nEnter 4 to clear the database");
			/* Input for taking a choice */
			try {
				String str = p.br.readLine();
				// System.out.println(str);
				choice = Integer.parseInt(str);
			} catch (Exception e) {
				e.printStackTrace();
			}
			switch (choice) {
			case 1:
				try {
					p.populateStations();
				} catch (Exception e) {
					e.printStackTrace();
				}
				break;
			case 2:
				try {
					p.populateTracks();
				} catch (Exception e) {
					e.printStackTrace();
				}
				break;
			case 4:
				try {
					p.clearDatabase();
				} catch (Exception e) {
					e.printStackTrace();
				}
				break;
			default:
				break;
			}
			// System.out.println("Enter 1 to continue and 0 to discontinue");
			try {
				choice = Integer.parseInt(p.br.readLine());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		p.closeDatabase();

	}

	public int getTotal() {
		return total;
	}

	public void setTotal(int total) {
		this.total = total;
	}
}
